<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Library.Database.Adapter
 */
class Dmf_Database_Adapter_Mysql extends Dmf_Database_Adapter_Abstract
{
    /**
     * The PDO connection object.
     * 
     * @var PDO 
     */
    private $_PDO;
    
    /**
     * PDO Fetch mode
     * 
     * @var int 
     */
    private $_fetchMode = PDO::FETCH_ASSOC;
    
    /**
     * All PDO connection objects.
     * 
     * @var array 
     */
    private static $_connections = array();
    
    /**
     * This is actually a shortcut to PDO::setAttribute
     * 
     * @param string $index
     * @param string $value 
     */
    public function setAttr( $index, $value )
    {
        if ( $index == 'fetchMode' )
        {
            $this->_fetchMode = $value;
            return;
        }
        
        $this->_PDO->setAttribute( $index, $value );
    }
    
    /**
     * Get PDO connection object
     * 
     * @return PDO 
     */
    public function getConnection()
    {
        if ( ! $this->_PDO instanceof PDO )
        {
            foreach( self::$_connections as $connection )
            {
                if ( $connection['database'] == $this->_settings['database'] && $connection['server'] == $this->_settings['server'] && $connection['username'] == $this->_settings['username'] && $connection['password'] == $this->_settings['password'] )
                {
                    $this->_PDO = $connection['pdo'];
                    
                    return $this->_PDO;
                }
            }
            
            $this->_PDO = new PDO( 'mysql:dbname=' . $this->_settings['database'] . ';host=' . $this->_settings['server'], $this->_settings['username'], $this->_settings['password'] );

            self::$_connections[] = array_merge( $this->_settings, array(
                'pdo' => $this->_PDO
            ) );
        }
        
        $this->_PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
        $this->_PDO->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true );
        
        return $this->_PDO;
    }
    /**
     * Execute query
     * 
     * @param string $query
     * @return array
     * @throws Exception 
     */
    public function query( $query )
    {
        $parameters = func_get_args();
        
        //Query is actually parameter 0
        unset( $parameters['0'] );
        
        //Index is 1 because indexes aren't changed since unsettings first
        if ( isset( $parameters['1'] ) && is_array( $parameters['1'] ) ) 
        {
            $parameters = $parameters['1'];
            
            unset( $parameters['0'] );
            
            if ( isset( $parameters['1'] ) && ! isset( $parameters['2'] ) && is_array( $parameters['1'] ) )
            {
                $parameters = $parameters['1'];
            }
        }
        
        $parameters = array_values( $parameters );
        
        $q = $this->getConnection()->prepare( $query );
        
        //If query failed
        if ( ! is_object( $q ) && Dmf_Application::getInstance()->getConfig()->asObject()->application->debug )
        {
            $err = $this->getConnection()->errorInfo();
            
            throw new PDOException( end( $err ) );
        }
        
        if ( count( $parameters ) > 0 )
        {
            $q->execute( $parameters );
        }
        else
        {
            $q->execute();
        }
        
        return $q;
    }
    
    /**
     * Fetch all rows
     * 
     * @param string $query
     * @return array 
     */
    public function fetchAll( $query )
    {
        return $this->query( $query, func_get_args() )->fetchAll( $this->_fetchMode );
    }
    
    /**
     * Fetch only the first row
     * 
     * @param string $query
     * @return array 
     */
    public function fetchRow( $query )
    {
        return $this->query( $query, func_get_args() )->fetch( $this->_fetchMode );
    }
    
    /**
     * Get sql result
     * 
     * @param string $query
     * @return boolean 
     */
    public function result( $query )
    {
        return is_bool( $this->fetchRow( $query ) );
    }
    
    /**
     * Count all rows
     * 
     * @param string $query
     * @return int 
     */
    public function rowCount( $query )
    {
        return $this->query( $query, func_get_args() )->rowCount( $this->_fetchMode );
    }
    
    /**
     * Get last inserted id
     * 
     * @param null|string $name
     * @return string 
     */
    public function lastId( $name = null )
    {
        return $this->getConnection()->lastInsertId( $name );
    }
}